﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace testqwe
{
    //梯形块，采用递归算法进行排样，并利用回溯得到具体的排样图案
    class Right_trapezoid
    {
        public const double SQRT_THREE = 1.73205;
        public const double THIRD_OF_SQRT_THREE = 1.73205 / 3;

        private double upperBase;
        public double bottomBase;
        private int height;
        private int[] diameter;
        private double[] value;
        public Trapezoid_stripe[] stripe;
        double stopline;

        public int[] F;
        public int[] N;
        public int[] G;
        bool[] P;
        public double revalue;
        public int[] result;
        public List<int[]> pattern;


        public Right_trapezoid(double upperbase, int high, int[] d,double[] v,Trapezoid_stripe[] ts)
        {
            upperBase = upperbase;
            height = high;
            diameter = d;
            value = v;
            //
            bottomBase = upperbase + high * THIRD_OF_SQRT_THREE;
            stripe = ts;
            result = new int[Constant.BLK_NUM];
            pattern = new List<int[]>();
        }


        public void docompelx()
        {
            //由于并不知道那个高度点会排下条带，这里稀疏存储
            F = new int[height + 1]; //存储毛坯序号
            G = new int[height + 1]; //存储毛坯排数
            N = new int[height + 1];//存储毛坯个数
            revalue= reccomplex(height);
            seekback();
        }

        //实现递归排样
        private double reccomplex(int h)
        {
            double max = 0.0;
            for (int i = 0; i < Constant.BLK_NUM; i++)
            {
                if (h < stripe[i].width[0]) continue;
                for (int j = 0; j < Constant.ROW; j++)
                {
                    if (h < stripe[i].width[j]) break;
                    int nwidth = (int)(stripe[i].width[j] + 0.99999);
                    int bt=getbottombych(h);
                    int num = stripe[i].u[j, bt];
                    //递归的主要体现
                    double v =  num* value[i] + reccomplex(h - nwidth);
                    if (v > max)
                    {
                        max = v;
                        F[h] = i+1;
                        G[h] = j+1;
                        N[h] = num;
                    }
                }
            }
            return max;
        }


        //通过F、G数组中存储的信息进行回溯得到排样图案的具体信息
        private void seekback()
        {
            int h = height;
            while (F[h] != 0)
            {
                int[] tempresult = new int[4];
                int id = F[h] - 1;
                int row = G[h] - 1;
                int bt = getbottombych(h);
                int nwidth = (int)(stripe[id].width[row] + 0.99999);
               // int num = stripe[id].u[row, bt];
                int num = N[h];
                result[id] += num;
                h = h - nwidth;
                tempresult[0] = id;//当前条带中的毛坯序号
                tempresult[1] = row+1;//当前条带包含有几排毛坯
                tempresult[2] = num;//当前条带含有的毛坯个数
                tempresult[3] = nwidth;//当前条带的宽度
                pattern.Add(tempresult);
            }
        }
        
        //下面的函数都是一些工具，不一定都用到了
        //根据毛坯直径，及排数信息得到条带的宽度信息
        private double getstripeheight(int raws,int d)
        {
            return d + SQRT_THREE * d/2.0 * (raws - 1);
        }

        //排入一个条带之后，剩余梯形的下底长度
        private double getnewbottombase(double bottom, int raws,int d)
        {
            return bottom - THIRD_OF_SQRT_THREE * getstripeheight(raws,d);
        }

        //根据梯形下底及高得到梯形上底长度
        private double getupper(double bottom, double hi)
        {
            double n=bottom - hi * Constant.THIRD_OF_SQRT_THREE;
            return n > 0 ? n : 0;
        }

        //根据梯形上底及高得到梯形下底长度
        private double getbottom(double upper, double hi)
        {
            double n = upper + hi * Constant.THIRD_OF_SQRT_THREE;
            return n;
        }

        //根据梯形上底及下底得到梯形的高
        private double getheightbyupdandbottom(double upper, double bottom)
        {
            return (bottom - upper) * Constant.SQRT_THREE;
        }

        //已知梯形块上底upperBase，排入的条带高度为h，剩余梯形块高度为height - h，求得剩余梯形的下底
        private int getbottombyh(int h)
        {
            return (int)(upperBase + (height - h) * Constant.THIRD_OF_SQRT_THREE);
        }

        //已知上底，通过梯形的高求得梯形下底
        private int getbottombych(int h)
        {
            return (int)(upperBase + h * Constant.THIRD_OF_SQRT_THREE);
        }

    }
}
